CloudFormation StackSetsでSecurity Hubのコントロール無効化をOrganizations組織全体に適用する
AWS事業本部のイシザワです。
先日のアップデートでSecurity Hubのコントロール無効化をCloudFormationで設定できるようになりました。
これを利用して、コントロール無効化をOrganizations組織全体に適用してみようと思います。
設定内容
以下の設定を適用します。
- Organizations管理アカウントをSecurity Hubの管理アカウントとする
- 全アカウントで、セキュリティ標準は「AWS 基礎セキュリティのベストプラクティス v1.0.0」と「CIS AWS Foundations Benchmark v1.4.0」のみを有効化
- 全アカウントで、両セキュリティ標準のコントロール IAM.6 を無効化
- 適用先リージョンはバージニア北部リージョンのみ
手順
全アカウント・全リージョンでSecurity Hubが無効化されている状態を初期状態とします。手順はバージニア北部リージョンで実施します。
Organizations管理アカウントでのSecurity Hubの有効化
管理アカウントでSecurity Hubを有効化します。このとき、セキュリティ基準の「AWS 基礎セキュリティのベストプラクティス v1.0.0 を有効にする」と「CIS AWS Foundations Benchmark v1.2.0 を有効にする」に入っているチェックを外します。
委任管理者の設定
Security Hubコンソールの左ペインの「設定」をクリックし、設定欄の「一般」タブを選択します。 委任された管理者の設定項目の「委任された管理者アカウントID」にOrganizations管理アカウントのアカウントIDを入力し、「委任」をクリックします。
これにより、Security HubのOrganizations統合が有効化されます。
メンバーアカウントでのSecurity Hubの有効化
設定で「アカウント」タブを選択し、「Auto-enable default standards」をオフにして、上部バーの「このリージョンで組織のSecurity Hubを有効にする」の「有効化」をクリックします。
これにより、他メンバーアカウントでSecurity Hubが有効化され、新規アカウントでSecurity Hubが自動で有効化されるようになります。 「Auto-enable default standards」をオフにしたことで、新規に有効化されたSecurity Hubではデフォルトのセキュリティ標準が有効化されません。 これはCloudFormationでデプロイするセキュリティ標準と設定が競合することを防ぐために実施しています。
メンバーアカウントのSecurity Hubの設定
以下のCloudFormationテンプレートをCloudFormation StackSetsでメンバーアカウントに適用します。
カスタムリソース SecurityHubEnablingWaiter はセキュリティ標準のデプロイをSecurity Hubの有効化後に行うことを確実にするためのリソースです。 特にStackSetsの自動デプロイの際は、このリソースが無いとSecurity Hubの自動有効化の前にスタックのデプロイが実行されて失敗することがあります。
AWSTemplateFormatVersion: 2010-09-09 Resources: FSBPStandard: Type: AWS::SecurityHub::Standard DependsOn: SecurityHubEnablingWaiter Properties: StandardsArn: !Sub "arn:aws:securityhub:${AWS::Region}::standards/aws-foundational-security-best-practices/v/1.0.0" DisabledStandardsControls: - StandardsControlArn: !Sub "arn:aws:securityhub:${AWS::Region}:${AWS::AccountId}:control/aws-foundational-security-best-practices/v/1.0.0/IAM.6" Reason: "No checked" CISv14Standard: Type: AWS::SecurityHub::Standard DependsOn: SecurityHubEnablingWaiter Properties: StandardsArn: !Sub "arn:aws:securityhub:${AWS::Region}::standards/cis-aws-foundations-benchmark/v/1.4.0" DisabledStandardsControls: - StandardsControlArn: !Sub "arn:aws:securityhub:${AWS::Region}:${AWS::AccountId}:control/cis-aws-foundations-benchmark/v/1.4.0/1.6" Reason: "No checked" SecurityHubEnablingWaiter: Type: Custom::SecurityHubEnablingWaiter Properties: ServiceToken: !GetAtt CustomResourceFunction.Arn CustomResourceFunction: Type: AWS::Lambda::Function Properties: FunctionName: !Sub security-hub-enabling-waiter-function-${AWS::Region} Code: ZipFile: | import cfnresponse import boto3 import time client = boto3.client('securityhub') response_data = {} def handler(event, context): print(event) if event['RequestType'] == 'Create': while True: try: client.describe_hub() print("## Security Hub is subscribed.") cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) break except client.exceptions.InvalidAccessException: print ("## Security Hub is not subscribed. Sleep 10 seconds.") time.sleep(10) except Exception as e: print(e) cfnresponse.send(event, context, cfnresponse.FAILED, response_data) break else: cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) Handler: index.handler MemorySize: 128 Role: !GetAtt FunctionRole.Arn Runtime: python3.10 Timeout: 300 FunctionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub security-hub-enabling-waiter-role-${AWS::Region} AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" Policies: - PolicyName: describe-security-hub-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: securityhub:DescribeHub Resource: "*"
以下のコマンドでメンバーアカウントにセキュリティ標準をデプロイします。
# スタックセットの作成 aws cloudformation create-stack-set \ --stack-set-name enable-security-hub-standards \ --template-body file://enable-security-hub-standards.yml \ --permission-model SERVICE_MANAGED \ --capabilities CAPABILITY_NAMED_IAM \ --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=true # スタックインスタンスの作成 aws cloudformation create-stack-instances \ --stack-set-name enable-security-hub-standards \ --regions us-east-1 \ --deployment-targets OrganizationalUnitIds=$(aws organizations list-roots --query 'Roots[].Id' --output text) \ --operation-preferences MaxConcurrentPercentage=100,FailureTolerancePercentage=100
管理アカウントのSecurity Hubの設定
サービスマネージド型のStackSetsではOrganizations管理アカウントにデプロイできないので、以下のコマンドでセキュリティ標準をデプロイします。
# スタックの作成 aws cloudformation create-stack \ --stack-name enable-security-hub-standards \ --template-body file://enable-security-hub-standards.yml \ --capabilities CAPABILITY_NAMED_IAM
複数リージョンにデプロイする場合は、セルフマネージド型のStackSetsでデプロイするのが効率的です。
設定内容の確認
各メンバーアカウントにて、セキュリティ標準で「AWS 基礎セキュリティのベストプラクティス v1.0.0」と「CIS AWS Foundations Benchmark v1.4.0」が有効化されていることが確認できます。
また、各セキュリティ標準でコントロールIAM.6が無効化されていることを確認できます。
終わりに
CloudFormationでセキュリティ標準の設定が可能になったので、CloudFormation StackSetsで組織全体に設定を反映させてみました。 今までは、組織全体でのコントロールの無効化には複雑な仕組みが必要でしたが、このアップデートによってシンプルに設定できるようになったと思います。
既にSecurity Hubが有効化済みの場合は、デプロイするセキュリティ標準を事前に無効化していないとデプロイ時にエラーがでるのでご注意ください。
このブログが誰かの助けになれば幸いです。